package main;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RecursiveRank extends BaseRank {
	public static final String TERM_COUNT_FILE_NAME = "data/2.0-0.4-terms-par-07-2";

	public static final String FORMATTED_COMBINED_FILE_NAME = "data/2.0-0.4-par-07-2";

	public static final String TERM_WEIGHT_FILE_NAME = "data/topic-200-fa-weights.txt";

	public static final String OUTPUT_FILE_NAME = "data/recursive-rank-result";

	public static final int TOP_N = 1000;

	@Override
	public void rank() {
		try {
			readFormatted(FORMATTED_COMBINED_FILE_NAME);
			readTermCount(TERM_COUNT_FILE_NAME);
			readTermWeight(TERM_WEIGHT_FILE_NAME);
			BufferedWriter bw = new BufferedWriter(new FileWriter(OUTPUT_FILE_NAME));
			Set<Entry<String, Topic>> set = topics.entrySet();
			List<Entry<String, Topic>> list = new ArrayList<Entry<String, Topic>>(set);
			Collections.sort(list, new comEntry());
			for (Iterator<Entry<String, Topic>> iter = list.iterator(); iter.hasNext();) {
				Topic topic = iter.next().getValue();
				reRank(topic);
				write(topic, bw);
			}
			bw.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	private void write(Topic topic, BufferedWriter bw) {
		try {
			for (Iterator<List> itL = topic.getOutput().iterator(); itL.hasNext();) {
				List<Passage> subList = itL.next();
				for (Iterator<Passage> itP = subList.iterator(); itP.hasNext();) {
					Passage psg = itP.next();
					bw.write(psg.getOutString() + "\r\n");
				}
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	private void reRank(Topic topic) {
		Collections.sort(topic.getInput(), new CompKeywords());
		List<List> outerList = new ArrayList<List>();
		int i = 0;
		for (Iterator<KeywordsWeight> itI = topic.getInput().iterator(); itI.hasNext() && i < TOP_N; i++) {
			KeywordsWeight kw = itI.next();
			if (outerList == null || outerList.isEmpty()) {
				List<Passage> list1 = new ArrayList<Passage>();
				List<Passage> list2 = new ArrayList<Passage>();
				for (Iterator<Passage> itP = topic.getPassages().iterator(); itP.hasNext();) {
					Passage psg = itP.next();
					if (isContains(psg.getFoundTerms(), kw.getExpression())) {
						list1.add(psg);
					} else {
						list2.add(psg);
					}
				}
				outerList.add(list1);
				outerList.add(list2);
			} else {
				List<List> tmpList = new ArrayList<List>();
				for (Iterator<List> itO = outerList.iterator(); itO.hasNext();) {
					List<Passage> list1 = new ArrayList<Passage>();
					List<Passage> list2 = new ArrayList<Passage>();
					List<Passage> subList = itO.next();
					for (Iterator<Passage> itP = subList.iterator(); itP.hasNext();) {
						Passage psg = itP.next();
						if (isContains(psg.getFoundTerms(), kw.getExpression())) {
							list1.add(psg);
						} else {
							list2.add(psg);
						}
					}
					if (!list1.isEmpty())
						tmpList.add(list1);
					if (!list2.isEmpty())
						tmpList.add(list2);
				}
				outerList.clear();
				outerList.addAll(tmpList);
			}
		}
		topic.setOutput(outerList);
	}

	protected void readTermWeight(String filename) throws FileNotFoundException, IOException {
		BufferedReader fmt_file = new BufferedReader(new FileReader(filename));
		Topic topic = null;
		Pattern pt = Pattern.compile("Topic #(\\d+) .*");
		Pattern pk = Pattern.compile(".+,\\d+,[0-9]|\\.+%,[0-9]|\\.+");
		for (String tmp = fmt_file.readLine(); tmp != null; tmp = fmt_file.readLine()) {
			Matcher mt = pt.matcher(tmp);
			Matcher mk = pk.matcher(tmp);
			if (mt.find()) {
				topic = topics.get(mt.group(1));
				if (topic == null) {
					topic = new Topic();
					topic.setId(mt.group());
					topics.put(topic.getId(), topic);
				}
				// topic.addPassage(psg);
			} else if (mk.find()) {
				String[] kwArray = tmp.split(",");
				KeywordsWeight kw = new KeywordsWeight();
				kw.setExpression(kwArray[0].split(" "));
				kw.setExpressionCount(new Integer(kwArray[1]));
				kw.setFrequency(new Double(kwArray[2].replace("%", "")));
				kw.setProminence(new Double(kwArray[3]));
				topic.addInput(kw);
			} else {
				System.err.println(tmp);
			}
		}
		fmt_file.close();

	}

	protected class KeywordsWeight {
		private String[] expression;
		private int expressionCount;
		private Double frequency;
		private Double Prominence;

		public String[] getExpression() {
			return expression;
		}

		public void setExpression(String[] expression) {
			this.expression = expression;
		}

		public int getExpressionCount() {
			return expressionCount;
		}

		public void setExpressionCount(int expressionCount) {
			this.expressionCount = expressionCount;
		}

		public double getFrequency() {
			return frequency;
		}

		public void setFrequency(double frequency) {
			this.frequency = frequency;
		}

		public Double getProminence() {
			return Prominence;
		}

		public void setProminence(Double prominence) {
			Prominence = prominence;
		}

	}

	/**
	 * for sort by desc
	 * 
	 * @author zhaoyu
	 * 
	 */
	protected class CompKeywords implements Comparator<KeywordsWeight> {

		public int compare(KeywordsWeight o1, KeywordsWeight o2) {
			if (o1 == null && o2 == null) {
				return 0;
			}
			return o2.getProminence().compareTo(o1.getProminence());
		}

	}

	public static void main(String[] args) {
		RecursiveRank rr = new RecursiveRank();
		rr.rank();
	}

}
